package logic

import (
	"bytes"
	"context"
	"errors"
	"image/jpeg"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"

	"imagehandle/internal/pkg/img"
	"imagehandle/internal/pkg/net"
	"imagehandle/internal/svc"
	"imagehandle/internal/types"

	lls "github.com/emirpasic/gods/stacks/linkedliststack"
	"github.com/zeromicro/go-zero/core/logx"
)

type IdentifyKeywordLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewIdentifyKeywordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *IdentifyKeywordLogic {
	return &IdentifyKeywordLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *IdentifyKeywordLogic) IdentifyKeyword(req *types.IdentifyKeywordRequest, w http.ResponseWriter) (err error) {
	imgData, err := http.Get(req.Url)
	if err != nil {
		return errors.New("文件URL获取失败")
	}
	defer imgData.Body.Close()

	data, err := ioutil.ReadAll(imgData.Body)
	if err != nil {
		return errors.New("文件解析出错")
	}

	body := bytes.NewReader(data)
	var contents []*string
	_, err = net.New().Path(l.svcCtx.Config.ImageServiceHost).Post("/lt_ocr").Body(body).ReceiveSuccess(&contents)
	if err != nil {
		logx.Errorf(err.Error())
		return
	}
	resps := make([][]*types.Axis, 0)
	for _, str := range contents {
		res, err := ParseData(*str)
		if err != nil {
			logx.Errorf(err.Error())
			return errors.New("数据解析错误")
		}
		// 判断文字是否符合条件
		if strings.Contains(res.Content, req.Keyword) {
			resps = append(resps, res.Axises)
		}
	}
	img, err := img.DrawRectOnImage(data, resps)
	if err != nil {
		return err
	}
	w.Header().Set("Content-Type", "image/jpeg")
	// 设置Content-Disposition
	w.Header().Set("Content-Disposition", "attachment; filename=new.png")
	err = jpeg.Encode(w, img, nil)
	if err != nil {
		return err
	}
	return nil
}

func ParseData(input string) (*types.SimpleIdentidyKeyword, error) {
	stack := lls.New()
	resp := &types.SimpleIdentidyKeyword{
		Axises: make([]*types.Axis, 0),
	}
	for i := 0; i < len(input); i++ {
		val := input[i]
		if val == '[' {
			stack.Push(val)
		} else if val >= '0' && val <= '9' {
			tmpStr := ""
			j := i
			for j < len(input) {
				if (input[j] >= '0' && input[j] <= '9') || input[j] == '.' {
					tmpStr = tmpStr + string(input[j])
				} else {
					break
				}
				j++
			}
			val, err := strconv.ParseFloat(tmpStr, 64)
			if err != nil {
				return nil, err
			}
			stack.Push(val)
			i = j - 1
		} else if val == ']' {
			val1, ok := stack.Pop()
			if !ok {
				return nil, errors.New("错误操作")
			}
			if val, ok := val1.(byte); ok && val == '[' {
				// 从此处直接截取到后面的所有数据进行赋值给content
				tmpContent := input[i:]
				n := 0
				for n < len(tmpContent) {
					if tmpContent[n] == ']' || tmpContent[n] == ',' || tmpContent[n] == ' ' {
						n++
						continue
					}
					break
				}
				resp.Content = tmpContent[n:]
				return resp, nil
			}
			val2, ok := stack.Pop()
			if !ok {
				return nil, errors.New("错误操作")
			}
			_, ok = stack.Pop()
			if !ok {
				return nil, errors.New("错误操作")
			}
			fval1 := val1.(float64)
			fval2 := val2.(float64)
			axis := &types.Axis{
				Y: fval1,
				X: fval2,
			}
			resp.Axises = append(resp.Axises, axis)
		}
	}
	return resp, nil
}
